package me.lc.hammerheads.sprite;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

import me.lc.hammerheads.core.GameManager;
import me.lc.hammerheads.core.GameMap;
import me.lc.hammerheads.core.GameSystem;
import me.lc.hammerheads.util.AudioHelper;

import com.wiyun.engine.actions.Action.Callback;
import com.wiyun.engine.actions.Animate;
import com.wiyun.engine.actions.FadeTo;
import com.wiyun.engine.actions.IntervalAction;
import com.wiyun.engine.actions.Sequence;
import com.wiyun.engine.nodes.Animation;
import com.wiyun.engine.nodes.Director;
import com.wiyun.engine.nodes.Label;
import com.wiyun.engine.nodes.Node;
import com.wiyun.engine.nodes.Sprite;
import com.wiyun.engine.types.WYColor3B;
import com.wiyun.engine.types.WYPoint;
import com.wiyun.engine.types.WYRect;
import com.wiyun.engine.utils.ResolutionIndependent;

/**
 * 锤子
 * 
 * @author Administrator
 * 
 */
public class Hammer extends Node {
	Sprite hammer;
	Animation animHammerFirstHalf;
	Animation animHammerLastHalf;

	HammerFirstHalfCallback firstHalfCallback;
	HammerLastHalfCallback lastHalfCallback;

	// 双倍威力锤子
	Sprite doubleHammer;
	Animation doubleAnimHammerFirstHalf;
	Animation doubleAnimHammerLastHalf;
	Label doubleHammerCount;

	ConcurrentLinkedQueue<WYPoint> clickQueue = new ConcurrentLinkedQueue<WYPoint>();
	Object hammerSyncObj = new Object();
	boolean isKnocking = false;
	Timer knockTimer;

	Sprite miss;
	Sprite strike;
	Sprite strike_ineffect;

	public static float HammerItemWidth = ResolutionIndependent.resolveDp(80);

	// 击打队列大小
	private static int HammerQueueCount = 6;
	private static float HammerSpeed = 0.05f;

	public void cancelTimer() {
		try {
			if (knockTimer != null) {
				knockTimer.cancel();
				knockTimer = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Hammer() {

		hammer = Sprite.make(GameSystem.tex_hammer1,
				WYRect.make(0, 0, HammerItemWidth, HammerItemWidth));
		hammer.setVisible(false);
		this.addChild(hammer);
		animHammerFirstHalf = new Animation(0);
		animHammerFirstHalf.addFrame(HammerSpeed, frameAt(0), frameAt(1),
				frameAt(2), frameAt(3));

		animHammerLastHalf = new Animation(0);
		animHammerLastHalf.addFrame(HammerSpeed, frameAt(4), frameAt(5),
				frameAt(6));

		if (knockTimer != null) {
			knockTimer.cancel();
			knockTimer = null;
		}
		knockTimer = new Timer();
		knockTimer.schedule(new HammerTimerTask(), 200, 200);

		miss = Sprite.make(GameSystem.tex_missing);
		miss.setScale(1.3f);
		miss.setPosition(Hammer.HammerItemWidth / 3.0f, 0);
		miss.setVisible(false);
		addChild(miss);

		strike = Sprite.make(GameSystem.tex_strike);
		strike.setPosition(Hammer.HammerItemWidth / 3.0f, 0);
		strike.setVisible(false);
		addChild(strike);

		strike_ineffect = Sprite.make(GameSystem.tex_strike_ineffective);
		strike_ineffect.setPosition(Hammer.HammerItemWidth / 3.0f, 0);
		strike_ineffect.setScale(1.3f);
		strike_ineffect.setVisible(false);
		addChild(strike_ineffect);

		// 初始化双倍
		doubleHammer = Sprite.make(GameSystem.tex_doubleHammer, frameAt(0));
		doubleHammer.setVisible(false);
		addChild(doubleHammer);
		doubleAnimHammerFirstHalf = new Animation(0);
		doubleAnimHammerFirstHalf.addFrame(HammerSpeed, frameAt(0), frameAt(1),
				frameAt(2), frameAt(3));

		doubleAnimHammerLastHalf = new Animation(0);
		doubleAnimHammerLastHalf.addFrame(HammerSpeed, frameAt(4), frameAt(5),
				frameAt(6));

		doubleHammerCount = Label.make("0", 20);
		doubleHammerCount.setColor(WYColor3B.make(55, 55, 0));
		doubleHammerCount.setPosition(0, HammerItemWidth / 4.0f);
		doubleHammerCount.setVisible(false);
		addChild(doubleHammerCount);

		firstHalfCallback = new HammerFirstHalfCallback();
		lastHalfCallback = new HammerLastHalfCallback();
	}

	/**
	 * 
	 */
	public synchronized void knock(WYPoint point) {
		if (clickQueue.size() < HammerQueueCount) {
			clickQueue.add(point);
		}
	}

	private void knock() {
		isKnocking = true;
		WYPoint point = clickQueue.peek();
		if (point != null) {
			this.setPosition(point.x - Hammer.HammerItemWidth / 3.0f, point.y);

			Animate hammerA1 = Animate.make(animHammerFirstHalf);
			hammerA1.autoRelease();
			hammerA1.setCallback(firstHalfCallback);
			Animate hammerA2 = Animate.make(animHammerLastHalf);
			hammerA2.autoRelease();
			hammerA2.setCallback(lastHalfCallback);

			Sequence seq1 = (Sequence) Sequence.make(hammerA1, hammerA2)
					.autoRelease();
			hammer.runAction(seq1);

			Animate doubleHmA1 = Animate.make(doubleAnimHammerFirstHalf);
			doubleHmA1.autoRelease();
			Animate doubleHmA2 = Animate.make(doubleAnimHammerLastHalf);
			doubleHmA2.autoRelease();

			Sequence seq2 = (Sequence) Sequence.make(doubleHmA1, doubleHmA2)
					.autoRelease();
			doubleHammer.runAction(seq2);

			AudioHelper.hammerAction();
			if (GameManager.instance.getDoubleHammerCount() <= 0) {
				hammer.setVisible(true);
				doubleHammer.setVisible(false);
				doubleHammerCount.setVisible(false);
			} else {
				doubleHammerCount.setVisible(true);
				doubleHammerCount.setText((GameManager.instance
						.getDoubleHammerCount() - 1) + "");
				doubleHammer.setVisible(true);
				hammer.setVisible(false);
			}
		}
	}

	private WYRect frameAt(int x) {
		return WYRect.make(x * HammerItemWidth, 0, HammerItemWidth,
				HammerItemWidth);
	}

	class HammerFirstHalfCallback implements Callback {

		@Override
		public void onStart(int arg0) {

		}

		@Override
		public synchronized void onStop(int arg0) {
			WYPoint point = clickQueue.poll();
			if (point != null) {
				int result = GameMap.instance.hit(point);
				switch (result) {
				case 0:
					// 没打中
					showHammerAlert(miss, 0.5f);
					AudioHelper.miss();
					break;
				case 1:
					// 成功打中
					showHammerAlert(strike, 0.3f);
					AudioHelper.knock();
					break;
				case 2:
					break;
				case 3:
					// 打击失败
					showHammerAlert(strike_ineffect, 0.5f);
					AudioHelper.knockHat();
					break;
				default:
					break;
				}
			}
		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}
	}

	class HammerLastHalfCallback implements Callback {

		@Override
		public void onStart(int arg0) {

		}

		@Override
		public synchronized void onStop(int arg0) {
			synchronized (hammerSyncObj) {
				isKnocking = false;
			}
			hammer.setVisible(false);
			doubleHammer.setVisible(false);
			doubleHammerCount.setVisible(false);
			// 恢复原状
			hammer.setTextureRect(frameAt(0));
			doubleHammer.setTextureRect(frameAt(0));
		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}
	}

	private void showHammerAlert(Sprite alertSprite, float duration) {
		IntervalAction action = (IntervalAction) FadeTo.make(duration, 255, 50)
				.autoRelease();
		action.setCallback(new AlertActionCallback(alertSprite));
		alertSprite.runAction(action);
	}

	class AlertActionCallback implements Callback {
		Sprite alert;

		public AlertActionCallback(Sprite alert) {
			this.alert = alert;
		}

		@Override
		public void onStart(int arg0) {
			alert.setVisible(true);
		}

		@Override
		public void onStop(int arg0) {
			alert.setVisible(false);
		}

		@Override
		public void onUpdate(int arg0, float arg1) {

		}

	}

	class HammerTimerTask extends TimerTask {

		@Override
		public void run() {
			synchronized (hammerSyncObj) {
				if (!isKnocking && clickQueue.peek() != null) {
					Director.getInstance().runOnGLThread(new Runnable() {

						@Override
						public void run() {
							knock();
						}
					});

				}
			}
		}

	}
}
